package com.czy.common.aspect;

import com.czy.common.annotation.SystemControllerLog;
import com.czy.utils.ServletUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

/**
 * @author czy
 * @date 2021/3/29
 * @description 日志切面
 */
@Slf4j
@Aspect
@Component
public class SystemLogAspect {

    /**controller层切点*/
    @Pointcut("@annotation(com.czy.common.annotation.SystemControllerLog)")
    public void controllerAspect(){}

    /**service层切点*/
    @Pointcut("@annotation(com.czy.common.annotation.SystemServiceLog)")
    public void serviceAspect(){}

    /**
     * 前置通知
     * @param joinPoint
     */
    @Before("controllerAspect()")
    public void doBefore(JoinPoint joinPoint){
        HttpServletRequest request = ServletUtils.getRequest();
        try {
            log.info("===================请求内容===================");
            log.info("方法描述: {}",getControllerMethodDescription(joinPoint));
            log.info("请求地址: {}", request.getRequestURL().toString());
            log.info("请求方法: {}", request.getMethod());
            log.info("请求ip: {}",request.getRemoteAddr());
            log.info("请求参数如下: ");
            // 参数值
            Object[] args = joinPoint.getArgs();
            // 参数名称
            String[] argNames = ((MethodSignature)joinPoint.getSignature()).getParameterNames();
            if (args != null && args.length > 0) {
                for (int i = 0; i < args.length; i++) {
                    log.info(argNames[i]+"="+args[i]);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("==前置通知异常==");
            log.error("异常信息：{}",e.getMessage());
        }
    }

    /**
     * 获取方法描述
     * @param joinPoint
     * @return
     * @throws Exception
     */
    public static String getControllerMethodDescription(JoinPoint joinPoint) throws Exception {
        String targetName = joinPoint.getTarget().getClass().getName();
        //目标方法名
        String methodName = joinPoint.getSignature().getName();
        Object[] arguments = joinPoint.getArgs();
        Class targetClass = Class.forName(targetName);
        Method[] methods = targetClass.getMethods();
        String description = "";
        for (Method method:methods) {
            if (method.getName().equals(methodName)){
                Class[] clazzs = method.getParameterTypes();
                if (clazzs.length==arguments.length){
                    description = method.getAnnotation(SystemControllerLog.class).description();
                    break;
                }
            }
        }
        return description;
    }


}
